﻿using System;
using System.Threading;
using nRoute.Components;
using nRoute.Components.Composition;
using nRoute.Utilities;

namespace nRoute.Components.Composition
{
    public class ResourceLocator
        : ResourceLocatorBase
    {
        private readonly Type _resourceType;
        private readonly Type _implementationType;
        private ILifetimeManager _lifetimeManager;

        public ResourceLocator(Type resourceType, Type implementationType, ILifetimeManager lifetimeManager)
        {
            Guard.ArgumentNotNull(resourceType, "resourceType");
            Guard.ArgumentNotNull(lifetimeManager, "lifetimeManager");

            _resourceType = resourceType;
            _implementationType = implementationType;
            _lifetimeManager = lifetimeManager;
        }

#region Properties

        public Type ResourceType
        {
            get { return _resourceType; }
        }

        public Type ImplementationType
        {
            get { return _implementationType ?? _resourceType; }
        }

        protected ILifetimeManager LifetimeManager
        {
            get { return _lifetimeManager; }
        }

#endregion

#region Overrides

        protected override Object GetInstance(ITypeBuilder typeBuilder)
        {
            if (_lifetimeManager != null)
            {
                if (_lifetimeManager != null && !this.IsDisposed)
                {
                    return _lifetimeManager.ManageBuild(typeBuilder, CreateResourceInstance);
                }
            }
            return null;
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_lifetimeManager != null)
                {
                    var _disposable = Interlocked.Exchange<ILifetimeManager>(ref _lifetimeManager, null);
                    if (_disposable != null) _disposable.Dispose();
                }
            }
        }

#endregion 

#region Helpers

        protected virtual Object CreateResourceInstance(ITypeBuilder typeBuilder)
		{
			return typeBuilder.BuildType(_implementationType ?? _resourceType);			
		}
		
#endregion

        ~ResourceLocator() { Dispose(false); }

    }
}
